package com.pzl.vca;

import android.Manifest;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.hardware.Camera;
import android.util.AttributeSet;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.core.app.ActivityCompat;

import java.io.IOException;

//1.绑定了手机camera的surfaceView ,用来显示本地摄像头的图像数据
//2.编码压缩摄像头原始图像数据
//3.把编码压缩好的图像帧数据通过网络发送
public class LocalSurfaceView extends SurfaceView implements SurfaceHolder.Callback, Camera.PreviewCallback {
    static final String TAG = "jinx_videochatA";

    private Camera.Size size;
    private Camera mCamera;

    //DSP硬件编码压缩图像数据
    PushLiveEncodec pushLiveEncodec;

    public LocalSurfaceView(Context context, AttributeSet attrs) {
        super(context, attrs);
        getHolder().addCallback(this);
    }

    @Override
    public void surfaceCreated(@NonNull SurfaceHolder holder) {
        Log.i(TAG, "surfaceCreated");
        if (ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
            Toast.makeText(getContext(), "无相机权限", Toast.LENGTH_SHORT).show();
            return;
        }

        int width = config.getIntExtra("width", -1);
        int height = config.getIntExtra("height", -1);
        //本机推送服务端口
        int port = config.getIntExtra("port", -1);

        //网络数据分发
        NetDispatcher netDispatcher = new NetDispatcher(port);
        pushLiveEncodec = PushLiveEncodec.getInstance(width, height);
        pushLiveEncodec.setNetDispatcher(netDispatcher);
        //surfaceView创建完成就开启摄像头，接收并显示本地摄像头图像数据
        startPreview();
    }

    //全局的预览帧数据的缓存，通过内存复用来提高预览的效率（不要操作系统的数据，以免发生异常，要使用就拷贝出来操作）
    byte[] globalPreviewDataBuffer;

    private void startPreview() {
        //打开后置摄像头
        mCamera = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK);
        Camera.Parameters parameters = mCamera.getParameters();
        //获取预览图像的尺寸等封装数据
        size = parameters.getPreviewSize();
        try {
            //设置用来渲染显示camera预览图像的surfaceView
            mCamera.setPreviewDisplay(getHolder());
            //由于摄像头硬件是横向的，旋转摄像头图像使其摆正
            mCamera.setDisplayOrientation(90);
            globalPreviewDataBuffer = new byte[size.width * size.height * 3 / 2];
            //在打开摄像头预览前先分配一个buffer地址
            mCamera.addCallbackBuffer(globalPreviewDataBuffer);
            //帧数据回调
            mCamera.setPreviewCallbackWithBuffer(this);
            //启动预览
            mCamera.startPreview();
            //配置编码器参数，启动编码器
            pushLiveEncodec.startLive();
        } catch (IOException e) {
            e.printStackTrace();
            Log.i(TAG, e.getMessage());
        }
    }

    @Override
    public void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, int height) {

    }

    @Override
    public void surfaceDestroyed(@NonNull SurfaceHolder holder) {

    }

    @Override
    public void onPreviewFrame(byte[] bytes, Camera camera) {
        //Log.i(TAG, "onPreviewFrame  bytes.len = " + bytes.length);
        //获取到摄像头的原始数据yuv

        pushLiveEncodec.encodeFrame(bytes);

        //如果没有调用这个方法addCallbackBuffer(byte[]),帧回调函数就不会被调用,也就是说在每一次回调函数调用后都必须调用addCallbackBuffer(byte[]).(所以可以直接在onPreviewFrame中调用addCallbackBuffer(byte[]),即camera.addCallbackBuffer(data);),复用这个原来的内存地址即可.
        //一直复用原来开辟的那个内存空间了,视频数据data永远都只会保持在一个地址中,只是其中的内容在不断的变化
        mCamera.addCallbackBuffer(bytes);


    }


    private Intent config;

    public void setConfig(Intent config) {
        this.config = config;
    }


}
